<?php
namespace App\Extend\Wx;

require_once BASE_PATH.'/app/Extend/Wx/wxapi/WxPay.Api.php';
require_once BASE_PATH.'/app/Extend/Wx/wxapi/WxPay.JsApiPay.php';
require_once BASE_PATH.'/app/Extend/Wx/wxapi/WxPay.Data.php';
require_once BASE_PATH.'/app/Extend/Wx/wxapi/WxPay.Config.php';

class WxPay
{
	public function __construct()
	{
        

	}

	public function pay($data)
	{
		try{
            //①、获取用户openid
            $tools = new \JsApiPay();
            $openId = $data['openid'];
            //②、统一下单
            $input = new \WxPayUnifiedOrder();
            $input->SetBody($data['title']);
            $input->SetAttach($data['id']);
            $input->SetOut_trade_no($data['order_no']);
            $input->SetTotal_fee($data['real_amount']*100);//以分为单位
            $input->SetTime_start(date("YmdHis"));
            $input->SetTime_expire(date("YmdHis", time() + 600));
            $input->SetGoods_tag('话费充值_'.$data['id']);
            $input->SetNotify_url(config('web.website') . '/recharge/api/recharge_back');
            $input->SetTrade_type("JSAPI");
            $input->SetOpenid($openId);
            $config = new \WxPayConfig();
            $order = \WxPayApi::unifiedOrder($config, $input);
            $jsApiParameters = $tools->GetJsApiParameters($order);
            return ['errCode'=>0,'data'=>$jsApiParameters];
            
            
        }catch(\Exception $e){
            $err_str = $e->getMessage();
            $err_arr = explode("===", $err_str);
            $errstr = '微信服务器错误,请稍后再试';
            if(isset($err_arr[1])){
                $errdata = json_decode($err_arr[1],true);
                if(isset($errdata['return_msg'])){
                    $errstr = $errdata['return_msg'];
                }
            }
            return ['errCode'=>1,'msg'=>$errstr];
           
        }  
	}
    //微信退款
    public function refund($data)
    {
        try{
            $input = new \WxPayRefund();
            $input->SetOut_trade_no($data['order_no']);
            $input->SetTotal_fee($data['real_amount']*100);
            $input->SetRefund_fee($data['real_amount']*100);

            $config = new \WxPayConfig();
            $input->SetOut_refund_no($data['order_no']);
            $input->SetOp_user_id($config->GetMerchantId());
            $result = \WxPayApi::refund($config, $input);
            if(array_key_exists("return_code", $result)
                    && array_key_exists("result_code", $result)
                    && $result["return_code"] == "SUCCESS"
                    && $result["result_code"] == "SUCCESS")
                {
                    return ['errCode'=>0,'data'=>$result];
                }else{
                    return ['errCode'=>1,'msg'=>$result['err_code_des'].$result['err_code']];
                }
        } catch(\Exception $e) {
            $err_str = $e->getMessage();var_dump($err_str);die;
            $err_arr = explode("===", $err_str);
            $errstr = '微信服务器错误,请稍后再试';
            if(isset($err_arr[1])){
                $errdata = json_decode($err_arr[1],true);
                if(isset($errdata['return_msg'])){
                    $errstr = $errdata['return_msg'];
                }
            }
            return ['errCode'=>1,'msg'=>$errstr];
        } 
    }

    //转账到个人
    public function transfers($data)
    {
        try{
            
            $openId = $data['opend_id'];
            //②、统一下单
            $input = new \WxPayTransfersPerson();
            $input->SetDesc($data['desc']);
            $input->SetPartner_trade_no($data['order_no']);
            $input->SetAmount($data['amount']*100);//以分为单位
            $input->SetCheck_name('NO_CHECK');
            $input->SetOpenid($openId);
            $config = new \WxPayConfig();
            $result = \WxPayApi::transfersPerson($config, $input);
            if(array_key_exists("return_code", $result)
                    && array_key_exists("result_code", $result)
                    && $result["return_code"] == "SUCCESS"
                    && $result["result_code"] == "SUCCESS")
                {
                    return ['errCode'=>0,'data'=>$result];
                }else{
                    return ['errCode'=>1,'msg'=>$result['err_code_des'].$result['err_code']];
                }
            
            
        }catch(\Exception $e){
            $err_str = $e->getMessage();var_dump($err_str);die;
            $err_arr = explode("===", $err_str);
            $errstr = '微信服务器错误,请稍后再试';
            if(isset($err_arr[1])){
                $errdata = json_decode($err_arr[1],true);
                if(isset($errdata['return_msg'])){
                    $errstr = $errdata['return_msg'];
                }
            }
            return ['errCode'=>1,'msg'=>$errstr];
           
        }  
    }

    //转账到银行卡
    public function payBank($data)
    {
        try{
            
            $input = new \WxPayPayBank();
            $input->SetPartner_trade_no($data['order_no']);
            $input->SetAmount($data['amount']*100);//以分为单位
            $input->SetEnc_bank_no($this->publicEncrypt($enc_bank_no));
            $input->SetEnc_true_name($this->publicEncrypt($enc_true_name));
            $input->SetBank_code($this->getBankCode($bank_code));
            $config = new \WxPayConfig();
            $result = \WxPayApi::payBank($config, $input);
            if(array_key_exists("return_code", $result)
                    && array_key_exists("result_code", $result)
                    && $result["return_code"] == "SUCCESS"
                    && $result["result_code"] == "SUCCESS")
                {
                    return ['errCode'=>0,'data'=>$result];
                }else{
                    return ['errCode'=>1,'msg'=>$result['err_code_des'].$result['err_code']];
                }
            
            
        }catch(\Exception $e){
            $err_str = $e->getMessage();var_dump($err_str);die;
            $err_arr = explode("===", $err_str);
            $errstr = '微信服务器错误,请稍后再试';
            if(isset($err_arr[1])){
                $errdata = json_decode($err_arr[1],true);
                if(isset($errdata['return_msg'])){
                    $errstr = $errdata['return_msg'];
                }
            }
            return ['errCode'=>1,'msg'=>$errstr];
           
        }  
    }

    /*
   * 银行编号列表，详情参考：https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_4
   * @params string $bank_name : 银行名称，4个汉字
   * return int $bank_code : 银行编码
   * */
  private function getBankCode($bank_name)
  {
    $bank_code = 0;
    switch ($bank_name){
      case '工商银行':  $bank_code = 1002; break;
      case '农业银行':  $bank_code = 1005; break;
      case '中国银行':  $bank_code = 1026; break;
      case '建设银行':  $bank_code = 1003; break;
      case '招商银行':  $bank_code = 1001; break;
      case '邮储银行':  $bank_code = 1066; break;
      case '交通银行':  $bank_code = 1020; break;
      case '浦发银行':  $bank_code = 1004; break;
      case '民生银行':  $bank_code = 1006; break;
      case '兴业银行':  $bank_code = 1009; break;
      case '平安银行':  $bank_code = 1010; break;
      case '中信银行':  $bank_code = 1021; break;
      case '华夏银行':  $bank_code = 1025; break;
      case '广发银行':  $bank_code = 1027; break;
      case '光大银行':  $bank_code = 1022; break;
      case '北京银行':  $bank_code = 1032; break;
      case '宁波银行':  $bank_code = 1056; break;
    }
    return $bank_code;
  }
  /**
   * 公钥加密，银行卡号和姓名需要RSA算法加密
   * @param string $data  需要加密的字符串，银行卡/姓名
   * @return null|string  加密后的字符串
   */
  private function publicEncrypt($data)
  {
    // 进行加密
    $pubkey = openssl_pkey_get_public(file_get_contents(ROOT_PATH.'data/cert/public_pkcs8.pem'));
    $encrypt_data = '';
    $encrypted = '';
    $r = openssl_public_encrypt($data,$encrypt_data,$pubkey,OPENSSL_PKCS1_OAEP_PADDING);
    if($r){//加密成功，返回base64编码的字符串
      return base64_encode($encrypted.$encrypt_data);
    }else{
      return false;
    }
  }
  /*
   * 获取公钥,格式为PKCS#1 转PKCS#8
   * openssl rsa -RSAPublicKey_in -in  <filename> -out <out_put_filename>
   * */
  private function get_pub_key()
  {
    $rsafile = ROOT_PATH.'data/cert/'.$this->appid.'_publicrsa.pem';
    if(!is_file($rsafile)){
      $data['mch_id'] = $this->mchid;
      $data['nonce_str'] = $this->random(12);
      $sign = $this->getParam($data);
      $dataXML="<xml>
      <mch_id>".$data['mch_id']."</mch_id>
      <nonce_str>".$data['nonce_str']."</nonce_str>
      <sign>".$sign."</sign>
      </xml>";
      $url = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
      $ret = $this->httpsPost($url,$dataXML,true);
      if($ret['return_code'] == 'SUCCESS' && isset($ret['pub_key'])){
        file_put_contents($rsafile,$ret['pub_key']);
        return $ret['pub_key'];
      }else{
        return null;
      }
    }else{
      return file_get_contents($rsafile);
    }
  }
  //对参数排序，生成MD5加密签名
  private function getParam($paramArray, $isencode=false)
  {
    $paramStr = '';
    ksort($paramArray);
    $i = 0;
    foreach ($paramArray as $key => $value)
    {
      if ($key == 'Signature'){
        continue;
      }
      if ($i == 0){
        $paramStr .= '';
      }else{
        $paramStr .= '&';
      }
      $paramStr .= $key . '=' . ($isencode?urlencode($value):$value);
      ++$i;
    }
    $stringSignTemp=$paramStr."&key=".$this->key;
    $sign=strtoupper(md5($stringSignTemp));
    return $sign;
  }
  /*
  * 将xml转换成数组
  * @params xml $xml : xml数据
  * return array $data : 返回数组
  */
  private function xmlToArray($xml)
  {
    //禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
    $val = json_decode(json_encode($xmlstring),true);
    return $val;
  }
  /*
  *  随机字符串
   * @param int $length 长度
   * @param string $type 类型
   * @param int $convert 转换大小写 1大写 0小写
   * @return string
  */
  private function random($length=10,$type='letter',$convert=false)
  {
    $config = array(
      'number'=>'1234567890',
      'letter'=>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
      'string'=>'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789',
      'all'=>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    );
   
    if(!isset($config[$type])) $type = 'letter';
    $string = $config[$type];
   
    $code = '';
    $strlen = strlen($string) -1;
    for($i = 0; $i < $length; $i++){
      $code .= $string[mt_rand(0, $strlen)];
    }
    if(!empty($convert)){
      $code = ($convert > 0)? strtoupper($code) : strtolower($code);
    }
    return $code;
  }
	
}